<!--
 * @Author: wangzhiyu <w19165802736@163.com>
 * @version: 1.0.0
 * @Date: 2024-02-29 09:26:30
 * @LastEditTime: 2025-01-16 14:48:15
 * @Description: Menu Interface
-->
<template>
  <!-- Joint Control Menu -->
  <div :class="`slider-block ${!menuShow ? 'expandMenu' : 'foldMenu'}`">
    <div class="swiperGroup">
      <el-switch class="swiperItem" v-model="isShowCollision" type="primary" size="large" @change="setCollision" active-text="Show Collision Model" inactive-text="Hide Collision Model" />
      <el-switch class="swiperItem" v-model="isOpenFollowLine" type="primary" size="large" @change="setFollowLine" active-text="Enable Follow Line" inactive-text="Disable Follow Line" />
    </div>

    <el-select size="large" placeholder="Preset Points" v-model="presetPointName" @change="setPresetPoint">
      <el-option v-for="item in presetPoint" :key="item.value" :label="item.label" :value="item.value" />
    </el-select>

    <div v-for="(item, index) in joints" :index="item[0]" :class="`slider-item ${controlJoint ? (controlJoint === item[0] ? 'slider-active' : 'slider-disable') : ''}`">
      <p class="demonstration">Joint {{ index + 1 }}</p>
      <el-slider :disabled="controlJoint ? (controlJoint === item[0] ? false : true) : false" v-model="jointsList[index].joint" show-input :min="jointsList[index].min" :max="jointsList[index].max" :step="0.01" @input="sliderInput(item[1], $event)" :format-tooltip="formatTooltip" />
    </div>
    <el-button class="editPose" type="primary" size="large" @click="editPose" v-if="isChangePose">Modify Pose</el-button>

    <!-- Button to Show/Hide Control Menu -->
    <div class="menuBtn" @click="changeMenuShow">
      <el-icon>
        <Expand v-if="!menuShow" />
        <Fold v-else />
      </el-icon>
    </div>
  </div>
</template>

<script setup>
import { ref, defineEmits, watch } from 'vue';
import { Expand, Fold } from '@element-plus/icons-vue';

// Receive parameters from parent component
const props = defineProps({
  // Robot arm joint information
  joints: {
    type: Array,
  },
  // Currently controlled joint
  controlJoint: {
    type: String,
  },
  // Whether the joint pose is currently being modified
  isChangePose: {
    type: Boolean,
  },
});

// Emit events
const emit = defineEmits(['sliderInput', 'setRobotCollision', 'editPose', 'usePresetPoint', 'setFollowLine']);

// Show/Hide menu (default is to show the menu)
const menuShow = ref(true);

// Toggle menu visibility
const changeMenuShow = () => (menuShow.value = !menuShow.value);

// Show/Hide collision model
const isShowCollision = ref(false);

// Enable/Disable follow line
const isOpenFollowLine = ref(true);

// Toggle follow line state
const setFollowLine = () => emit('setFollowLine', isOpenFollowLine.value);

// Save angle information for each joint to avoid affecting original data
const jointsList = ref([]);

// Current preset point
const presetPointName = ref();

// Preset points list
const presetPoint = ref([
  {
    label: 'Initial Position',
    value: JSON.stringify([0, 0, 0, 0, 0, 0]),
  },
  {
    label: 'Left Offset',
    value: JSON.stringify([0, 0, -1.57, 0, 0, 0]),
  },
  {
    label: 'Right Offset',
    value: JSON.stringify([0, 0, 1.57, 0, 0, 0]),
  },
]);

// Apply preset point
const setPresetPoint = value => {
  emit('usePresetPoint', JSON.parse(value));
};

// Watch for changes in joints to update slider content in real-time and save maximum and minimum joint angles for setting joint limits
watch(
  () => props.joints,
  newList => (jointsList.value = newList.map(item => ({ joint: item[1].angle, min: item[1].limit.lower, max: item[1].limit.upper }))),
  { deep: true }
);

// Format slider tooltip message
const formatTooltip = value => value.toFixed(2);

// Emit event to modify robot arm joint angle
const sliderInput = (joint, value) => emit('sliderInput', joint, value);

// Emit event to show/hide collision model
const setCollision = value => emit('setRobotCollision', value);

// Emit event to modify pose
const editPose = () => emit('editPose');

defineExpose({
  // Expose real-time angle data
  jointsList,
  // Expose currently selected preset point data
  presetPointName,
});
</script>

<style>
.el-select--large .el-select__wrapper,
.el-select-dropdown__item {
  font-size: 16px !important;
}
.el-switch__label span {
  font-size: 19px !important;
}
.el-slider__button {
  height: 15px !important;
  width: 15px !important;
}
.slider-block {
  width: 350px;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 10px;
  box-sizing: border-box;
  background-color: rgba(255, 255, 255, 0.6);
  transition: 0.5s;
}
.swiperGroup {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.swiperItem {
  margin: 15px 0;
  font-size: 20px;
}
.menuBtn {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 40px;
  height: 40px;
  position: absolute;
  top: 8%;
  right: 0;
  transform: translate(100%, 0);
  border-radius: 0% 7px 7px 0%;
  border: 1px solid #999;
  border-left-color: #fff;
  box-sizing: border-box;
  background-color: #fff;
}
.menuBtn .el-icon {
  font-size: 26px;
}
.expandMenu {
  transform: translateX(-100%);
}
.foldMenu {
  transform: translateX(0%);
}

.editPose {
  position: absolute;
  bottom: 2%;
  left: 3%;
  font-size: 20px !important;
}
.slider-item {
  padding: 10px;
  margin: 5px 0;
  box-sizing: border-box;
}
.slider-active,
.slider-disable {
  background-color: rgba(255, 255, 255, 0.8);
  border-radius: 10px;
  transition: 0.5s;
}
.slider-disable {
  color: #fff;
  background-color: rgba(0, 0, 0, 0.5);
}
</style>